﻿using System;
using System.Collections.Generic;
using UnityEngine;

namespace GameFramework.Battle.Core
{
    
    public enum EEffectDirection
    {
        None,
        /// <summary>
        /// 特效命中前方
        /// </summary>
        forward,
        /// <summary>
        /// 特效命中反方向
        /// </summary>
        backward
    }
    
    public enum EEffectType
    {
        General,
        Sub,
        AddCommander,
    }
    public enum EEffectBindType
    {
        /// <summary>
        /// 脱离节点存在
        /// </summary>
        World,
        /// <summary>
        /// 节点本地
        /// </summary>
        Local,
        /// <summary>
        /// 原点
        /// </summary>
        Origin
    }
#pragma warning disable 0618
    [ExecuteInEditMode]
    [DisallowMultipleComponent]
    public class EffectControl : MonoBehaviour
    {
        public static float precisionHi = 0.1f;
        public static float precisionCustom = 0.5f;
        public static float precisionColorCustom = 0.1f;

        public ParticleSystem[] particleSystemArr;
        public Renderer[] rendererArr;
        public EffectMeshUtility[] effectArr;
        public Animator[] animatorArr;

#if UNITY_EDITOR
        int byteTrans = 0;

        private void OnDisable()
        {
            if (Application.isPlaying)
                Debug.LogWarning(string.Format("{0} VB translate: {1} Byte", gameObject.name, byteTrans));
        }
#endif

        public void ForceInit()
        {
            particleSystemArr = gameObject.GetComponentsInChildren<ParticleSystem>(true);
            rendererArr = gameObject.GetComponentsInChildren<Renderer>(true);
            effectArr = gameObject.GetComponentsInChildren<EffectMeshUtility>(true);
            animatorArr = gameObject.GetComponentsInChildren<Animator>(true);

            for (int e = 0; e < effectArr.Length; e++)
            {
                effectArr[e].ForceInit();
            }
        }
        public void SetParticle()
        {
            particleSystemArr = gameObject.GetComponentsInChildren<ParticleSystem>();
        }

        void OnEnable()
        {
            if (!Application.isPlaying)
            {
                ForceInit();
            }

#if UNITY_EDITOR
            byteTrans = 0;
#endif
        }

        private void LateUpdate()
        {
            if (!Application.isPlaying)
                return;

            if (effectArr == null)
                return;

            for (int e = 0; e < effectArr.Length; e++)
            {
                EffectMeshUtility effect = effectArr[e];
                Renderer renderer = effect.meshRenderer;

                if (!effect.isActiveAndEnabled /*|| !renderer.isVisible*/)
                    continue;

                Vector4 color = effect.tintColor.linear;
                color = Mathf.Min(EffectMeshUtility.mColorRange, effect.mMultiplier) * color;

                if (color.w < 0.01f)
                {
                    renderer.enabled = false;
                    continue;
                }

                renderer.enabled = true;
                
                MeshFilter filter = effect.filter;
                MaterialPropertyBlock materialBlock = effect.materialBlock;
                List<Vector4> uvBuffer = effect.uvBuffer;
                bool bCopyData = (uvBuffer != null && filter != null && filter.sharedMesh != null);

                float c1 = EffectMeshUtility.PackM(color.x, color.y, EffectMeshUtility.mColorRange);
                float c2 = EffectMeshUtility.PackM(color.z, color.w, EffectMeshUtility.mColorRange);

                c1 = effect.mainTexIsClamp ? -c1 : c1;
                c2 = effect.maskTexIsClamp ? -c2 : c2;

                float d1 = EffectMeshUtility.PackScale(effect.mainTiling, EffectMeshUtility.TexScaleRange);
                float d2 = EffectMeshUtility.PackOffset(effect.mainOffset, EffectMeshUtility.TexOffsetRange);
                Vector4 pack1 = new Vector4(c1, c2, d1, d2);

                if (Vector4.Distance(pack1, effect._pack1) > 0.01f)
                {
                    effect._pack1 = pack1;

                    if (bCopyData)
                    {
                        for (int i = 0; i < uvBuffer.Count; i++)
                        {
                            uvBuffer[i] = pack1;
                        }
                        filter.sharedMesh.SetUVs(1, uvBuffer);
#if UNITY_EDITOR
                        byteTrans += uvBuffer.Count * 16;
#endif
                    }
                    else if (materialBlock != null)
                        materialBlock.SetVector(EffectMeshUtility.pack1ID, pack1);
                }

                if (effect.isMask)
                {
                    float b1 = EffectMeshUtility.V2Tofloat(effect.MaskBlock.x, effect.MaskBlock.y);
                    float b2 = EffectMeshUtility.V2Tofloat(effect.MaskBlock.z, effect.MaskBlock.w);
                    float e1 = EffectMeshUtility.PackScale(effect.maskTiling, EffectMeshUtility.TexScaleRange);
                    float e2 = EffectMeshUtility.PackOffset(effect.maskOffset, EffectMeshUtility.TexOffsetRange);
                    Vector4 pack2 = new Vector4(b1, b2, e1, e2);

                    if (Vector4.Distance(pack2, effect._pack2) > 0.01f)
                    {
                        effect._pack2 = pack2;

                        if (bCopyData)
                        {
                            for (int i = 0; i < uvBuffer.Count; i++)
                            {
                                uvBuffer[i] = pack2;
                            }
                            filter.sharedMesh.SetUVs(2, uvBuffer);

#if UNITY_EDITOR
                            byteTrans += uvBuffer.Count * 16;
#endif
                        }
                        else if (materialBlock != null)
                            materialBlock.SetVector(EffectMeshUtility.pack2ID, pack2);
                    }
                }

                if (renderer != null && materialBlock != null)
                    renderer.SetPropertyBlock(materialBlock);
            }
        }
    }
}
